
using System;

namespace Waymex.Gis.Shape
{
#if(PUBLIC)
	public abstract class ShapeBase
#else
	internal abstract class ShapeBase
#endif
	{
		internal ShapeType	m_enuType	= ShapeType.ShapeTypeNone;
		internal bool		m_blnValid	= false;
		
		internal const double NO_DATA = -10e39; //anything less than -10e38 will do

		internal const string ERR_MSG_1000 = "Error occurred during array creation.";
		internal const string ERR_MSG_1001 = "Invalid Shape Type.";
		internal const string ERR_MSG_1002 = "Invalid Attribute Collection. Attribute collections added to a ShapeFile object must contain the same list of attribute names and data types.";
		internal const string ERR_MSG_1003 = "Invalid Filename. Filenames must consist of 8 characters or less, and file extensions should not be specified.";

		public ShapeType Type
		{
			get
			{
				return m_enuType;
			}
		}
		internal enum ByteOrder
		{
			ByteOrderBigEndian,
			ByteOrderLittleEndian
		}

		public enum ShapeType
		{
			ShapeTypeNull = 0,
			ShapeTypePoint = 1,
			ShapeTypePolyLine = 3,
			ShapeTypePolygon = 5,
			ShapeTypeMultiPoint = 8,
			ShapeTypePointZ = 11,
			ShapeTypePolyLineZ = 13,
			ShapeTypePolygonZ = 15,
			ShapeTypeMultiPointZ = 18,
			ShapeTypePointM = 21,
			ShapeTypePolyLineM = 23,
			ShapeTypePolygonM = 25,
			ShapeTypeMultiPointM = 28,
			ShapeTypeMultiPatch = 31,
			ShapeTypeNone = -1
	}

		public ShapeBase()
		{
		}
		internal virtual byte[] ToByte()
		{
			return null;
		}
		internal bool ComparePoints(Point Point1, Point Point2)
		{
			if((Point1.ValueX == Point2.ValueX) && (Point1.ValueY == Point2.ValueY))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
//		internal bool ComparePoints(PointM Point1, PointM Point2)
//		{
//			//TODO: Find out if we should also compare the measure
//			if((Point1.ValueX == Point2.ValueX) && (Point1.ValueY == Point2.ValueY))
//			{
//				return true;
//			}
//			else
//			{
//				return false;
//			}
//		}
//
//		internal bool ComparePoints(PointZ Point1, PointZ Point2)
//		{
//			//TODO: Find out if we should also compare the measure
//			if((Point1.ValueX == Point2.ValueX) && (Point1.ValueY == Point2.ValueY) && (Point1.ValueZ == Point2.ValueZ))
//			{
//				return true;
//			}
//			else
//			{
//				return false;
//			}
//		}

		internal byte[] ConvertToByte(int intValue, ByteOrder enumEndian)
		{
			byte[] bytTemp = null;
			byte[] bytResult = null;
			try
			{

				int intUBound = 0;

				//convert the incomming data to bytes
				bytResult = BitConverter.GetBytes(intValue);
				
				//create a temporary array
				bytTemp = new byte[bytResult.Length];

				//big endian so swap the bytes around
				if(enumEndian == ByteOrder.ByteOrderBigEndian)
				{
					intUBound = bytResult.GetUpperBound(0);
					if(intUBound >= 0)
					{
						for(int f = 0; f <= intUBound; f++)
						{
							bytTemp[intUBound - f] = bytResult[f];
						}
						//update bytResult with the rearranged data
						bytResult = bytTemp;		
					}
				}
			}
			catch(Exception e)
			{
                throw new ShapeException(e.Message, e);
            }

			return bytResult;
		}

		internal byte[] ConvertToByte(double dblValue, ByteOrder enumEndian)
		{
			byte[] bytTemp = null;
			byte[] bytResult = null;
			try
			{

				int intUBound = 0;

				//convert the incomming data to bytes
				bytResult = BitConverter.GetBytes(dblValue);
				
				//create a temporary array
				bytTemp = new byte[bytResult.Length];

				//big endian so swap the bytes around
				if(enumEndian == ByteOrder.ByteOrderBigEndian)
				{
					intUBound = bytResult.GetUpperBound(0);
					if(intUBound >= 0)
					{
						for(int f = 0; f <= intUBound; f++)
						{
							bytTemp[intUBound - f] = bytResult[f];
						}
						//update bytResult with the rearranged data
						bytResult = bytTemp;		
					}
				}
			}
			catch(Exception e)
			{
				throw new ShapeException(e.Message, e);
			}

			return bytResult;
		}

		internal static byte[] ReDimPreserve(byte[] bytArray,int intNewDimension)
		{

			byte[] bytNewArray = null;
			
			try
			{
				//re-dimensions a byte array and preserves the contents
				if(intNewDimension <= 0 || intNewDimension == 0)
					throw new ArgumentException(ERR_MSG_1000);

				bytNewArray = new byte[intNewDimension];

				//copy any existing data
				if(bytArray != null)
					System.Array.Copy(bytArray,0,bytNewArray,0,bytArray.Length);
			}
			catch(Exception e)
			{
				throw new ShapeException(e.Message, e);
			}
			
			return bytNewArray;
		}

		internal static string[] ReDimPreserveS(string[] strArray, int intNewDimension)
		{
			string[] strNewArray = null;

			try
			{
				//re-dimensions a byte array and preserves the contents
				if(intNewDimension <= 0 || intNewDimension == 0)
					throw new ArgumentException(ERR_MSG_1000);

				strNewArray = new string[intNewDimension];

				//copy any existing data
				if(strArray != null)
					System.Array.Copy(strArray,0,strNewArray,0,strArray.Length);
			}
			catch(Exception e)
			{
				throw new ShapeException(e.Message, e);
			}
			return strNewArray;
		}
        internal byte[] ByteConcat(byte[] array1, byte[] array2)
        {

            byte[] data = null;
            int lenData1 = 0;
            int lenData2 = 0;

            try
            {
                //determine array lengths
                if (array1 != null)
                    lenData1 = array1.Length;
                if (array2 != null)
                    lenData2 = array2.Length;

                //create a new array to hold both incomming arrays
                data = new byte[lenData1 + lenData2];

                //copy the arrays
                if (lenData1 > 0)
                    Array.Copy(array1, 0, data, 0, lenData1);
                if (lenData2 > 0)
                    Array.Copy(array2, 0, data, lenData1, lenData2);

            }
            catch
            {
                //TraceLog.WriteError(e)
                throw;
            }

			
			return data;
			
		}

	}
}
